package cate.game.play.fighter;


import cate.common.table.d.GDPlay;
import cate.common.table.d.GDSkill;
import cate.game.play.proce.action.ctx.ActionCtx;
import cate.game.play.proce.stat.StatItem;
import cp.solution.util.collection.ListKit;
import cp.solution.util.collection.MapKit;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@NoteClass(value = "战绩", detail = "记录了fighter累计的伤害与治疗以及承受伤害")
public class FighterPerformance {

    @NoteField( "造成的伤害")
    public long damage = 0;

    @NoteField("造成的治疗")
    public long heal = 0;

    @NoteField("承受的伤害")
    public long hurt = 0;

    @NoteField("击杀数")
    public int kill = 0;

    @NoteField("阵亡数")
    public int dead = 0;

    @NoteField("回合统计数据")
    public List<RoundPerformance> rounds = new ArrayList<>();

    @NoteField("击杀记录")
    public List<FighterProfile> killList = new ArrayList<>();

    public RoundPerformance getRoundPerformance(int round) {
        for (RoundPerformance roundPerformance : rounds) {
            if (roundPerformance.round == round) {
                return roundPerformance;
            }
        }
        return null;
    }

    private RoundPerformance getOrBuildPerformance(int round) {
        RoundPerformance performance = getRoundPerformance(round);
        if (performance != null) {
            return performance;
        }
        performance = new RoundPerformance(round);
        rounds.add(performance);
        return performance;
    }

    public long calTotalHurt(int startRound, int endRound) {
        long total = 0;
        for (int i = startRound; i <= endRound; i++) {
            FighterPerformance.RoundPerformance performance = getRoundPerformance(i);
            if (performance != null) {
                total += performance.hurt;
            }
        }
        return total;
    }


    /**
     * 记录伤害行为（包括buff伤害）
     * @param action
     * @param actor
     * @param target
     * @param value
     */
    public static void recDamage(ActionCtx action, Fighter actor, Fighter target, int reason, long value) {
        if (value <= 0) {
            return;
        }
        actor.performance.damage += value;
        actor.performance.getOrBuildPerformance(action.getRound().index).damage += value;

        target.performance.hurt += value;
        target.performance.getOrBuildPerformance(action.getRound().index).hurt += value;

        if (GDPlay.HpReason.SKILL_HURT == reason) {
            action.getStat().add(new StatItem(actor.getPid(), target.getPid(), GDSkill.StatType.SKILL_DAMAGE, value));
        }
    }

    /**
     * 记录过量伤害
     * @param action
     * @param actor
     * @param target
     * @param value
     */
    public static void recOverFlowDamage(ActionCtx action, Fighter actor, Fighter target, long value){
        if (value <= 0) {
            return;
        }
        action.getStat().add(new StatItem(actor.getPid(), target.getPid(), GDSkill.StatType.OVER_FLOW_DAMAGE, value));
    }

    /**
     * 记录治疗行为(不包括吸血)
     * @param action
     * @param actor
     * @param target
     * @param value
     */
    public static void recHeal(ActionCtx action, Fighter actor, Fighter target, long value) {
        if (value <= 0) {
            return;
        }
        actor.performance.heal += value;
        action.getStat().add(new StatItem(actor.getPid(), target.getPid(), GDSkill.StatType.HEAL, value));
    }


    /** 记录击杀行为 */
    public static void recKill(ActionCtx action, Fighter actor, Fighter target) {
        if (actor == null) {
            return;
        }
        actor.performance.kill += 1;
        actor.performance.killList.add(new FighterProfile(target));
        actor.performance.getOrBuildPerformance(action.getRound().index).kill += 1;

        target.performance.dead += 1;
        action.getStat().add(new StatItem(actor.getPid(), target.getPid(), GDSkill.StatType.KILL, 1));
    }

    /** 记录暴击行为 */
    public static void recStrike(ActionCtx action, Fighter actor){
        actor.performance.getOrBuildPerformance(action.getRound().index).strike+=1;
    }

    /** 记录buff添加行为 */
    public static void recBuffAdd(ActionCtx action, Fighter actor,int buffProtoId){
        RoundPerformance roundPerformance = actor.performance.getOrBuildPerformance(action.getRound().index);
        int num = roundPerformance.buffAddMap.getOrDefault(buffProtoId, 0);
        roundPerformance.buffAddMap.put(buffProtoId, num+1);
    }

    /** 记录技能释放行为 */
    public static void recSkillCast(int round, Fighter actor,int skillProtoId){
        RoundPerformance roundPerformance = actor.performance.getOrBuildPerformance(round);
        int num = roundPerformance.skillCastMap.getOrDefault(skillProtoId, 0);
        roundPerformance.skillCastMap.put(skillProtoId, num+1);
    }

    public FighterPerformance copy(){
        FighterPerformance cp = new FighterPerformance();
        cp.damage = this.damage;
        cp.heal = this.heal;
        cp.hurt = this.hurt;
        cp.kill = this.kill;
        cp.dead = this.dead;
        cp.rounds = ListKit.cloneList(rounds, RoundPerformance::copy);
        cp.killList = ListKit.cloneList(killList, FighterProfile::copy);
        return cp;
    }


    @Override
    public String toString() {
        return "{造成伤害=" + damage + ",造成治疗=" + heal + ",承受伤害=" + hurt + "}";
    }


    public static class RoundPerformance {

        @NoteField("回合")
        public int round;

        @NoteField("造成的伤害")
        public long damage;

        @NoteField("承受的伤害")
        public long hurt;

        @NoteField("击杀数量")
        public int kill;

        @NoteField("暴击数量")
        public int strike;

        @NoteField("buff添加记录")
        public Map<Integer, Integer> buffAddMap = new HashMap<>();

        @NoteField("技能释放记录")
        public Map<Integer, Integer> skillCastMap = new HashMap<>();

        public RoundPerformance(int round) {
            this.round = round;
        }

        public RoundPerformance() {
        }



        public RoundPerformance copy() {
            RoundPerformance cp = new RoundPerformance();
            cp.round = round;
            cp.damage = damage;
            cp.hurt = hurt;
            cp.kill = kill;
            cp.strike = strike;
            cp.buffAddMap = MapKit.clone(buffAddMap);
            cp.skillCastMap = MapKit.clone(skillCastMap);
            return cp;
        }
    }

    public static class FighterProfile {
        public int pid;
        public byte pos;

        public FighterProfile() {
        }

        public FighterProfile(Fighter fighter) {
            this.pid = fighter.getPid();
            this.pos = fighter.getPos();
        }

        public FighterProfile copy(){
            FighterProfile cp = new FighterProfile();
            cp.pid = this.pid;
            cp.pos = this.pos;
            return cp;
        }
    }
}
